#ifndef _TCPLIB_LOCK_HPP_
#define _TCPLIB_LOCK_HPP_
#include "Common.hpp"
#include <pthread.h>


namespace tcplib
{

class Lock: public Noncopyable
{
    union {
        pthread_mutex_t mutex;
        pthread_spinlock_t spinlock;
    };

    const int _type;

public:
    enum {
        MUTEX,
        SPINLOCK,
    };

    Lock(int type = MUTEX)
        :_type(type)
    {
        if (_type == MUTEX) {
            pthread_mutex_init(&mutex, NULL);
        } else if (_type == SPINLOCK)
            pthread_spin_init(&spinlock, PTHREAD_PROCESS_PRIVATE);
        else 
            panic("No such lock type");
    }

    ~Lock()
    {
        if (_type == MUTEX)
            pthread_mutex_destroy(&mutex);
        else if (_type == SPINLOCK)
            pthread_spin_destory(&spinlock);
    }


    void lock()
    {
        if (_type == MUTEX)
            pthread_mutex_lock(&mutex);
        else if (_type == SPINLOCK)
            pthread_spin_lock(&spinlock);
    }


    void unlock()
    {
        if (_type == MUTEX)
            pthread_mutex_unlock(&mutex);
        else if (_type == SPINLOCK)
            pthread_spin_unlock(&spinlock);
    }

    int trylock()
    {
        if (_type == MUTEX)
            return pthread_mutex_trylock(&mutex);
        else if (_type == SPINLOCK)
            return pthread_spin_trylock(&spinlock);
    }
};


class ScopedLock : public Noncopyable
{
    Lock *_lock;
public:
    ScopedLock(Lock *lock)
        :_lock(lock) 
    {
        _lock->lock();
    }

    ScopedLock(Lock &lock)
        :_lock(&lock)
    {
        _lock->lock();
    }

    ~ScopedLock()
    {
        _lock->unlock();
    }
};


};


